/*题目描述
定义表示形状的抽象类及相应的派生类，并实现相关操作符重载。

（1）定义表示形状的抽象类Shape：

添加公有成员函数double Area()，用于计算形状面积；定义为纯虚函数；

添加公有成员函数void Show()，用于显示形状信息，定义为纯虚函数；

定义虚的析构函数；

重载比较操作符：==、>和<，用于比较两个形状面积的大小关系，返回值类型为bool，可以定义为成员函数或友元函数。



（2）从形状类Shape派生矩形类Rectangle：

添加double型的保护数据成员：rectWidth和rectHeight，分别表示矩形的宽度和高度；

定义带参构造函数；
重定义公有成员函数Show，打印矩形的宽度和高度，输出格式为“W: 宽度; H: 高度; Area: 面积”；
重定义公有成员函数Area，计算矩形面积。

（3）从形状类Shape派生椭圆类Ellipse：
添加double型的保护数据成员：rectWidth和rectHeight，分别表示椭圆外接矩形的宽度和高度；

定义带参构造函数；
重定义公有成员函数Show，打印椭圆外接矩形的宽度和高度，输出格式为“W: 宽度; H: 高度; Area: 面积”；
重定义公有成员函数Area，计算椭圆面积。



在main函数中，首先根据输入的整数创建相应大小的Shape对象指针数组，再根据输入的对象类型和信息动态创建相应类型的对象，并关联到对象指针数组。输入的信息格式如下：

3          // 对象指针数组的元素个数

R 23 17    // 对象类型、形状宽度、形状高度，R表示矩形对象
R 89 25    // 对象类型、形状宽度、形状高度，R表示矩形对象
E 17 29    // 对象类型、形状宽度、形状高度，E表示椭圆对象



接着通过调用Show成员函数输出所有对象的信息。

然后输出面积相等的形状对象的信息（要求使用重载的运算符“==”来判断对象的面积是否相等），输出格式如下：

Area of Shape[i] is equal to Shape[j]

最后将所有形状对象按面积从大到小排序（要求使用重载的运算符“>”来判断对象的面积的大小关系），并输出排序后的对象信息。

输入
对象数目

对象类型 对象的外接矩形宽度 对象的外接矩形高度

输出
排序前的对象信息

面积相等的对象信息

排序后的对象信息*/
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <assert.h>

using namespace std;

//定义表示形状的抽象类Shape
class Shape
{
public:
    //添加公有成员函数double Area()，用于计算形状面积；定义为纯虚函数
    virtual double Area()
    {
        return 0.0;
    }
    //添加公有成员函数void Show()，用于显示形状信息，定义为纯虚函数；
    virtual void Show() {}
    //虚的析构函数；
    virtual ~Shape() {}
//重载比较操作符：==、>和<，用于比较两个形状面积的大小关系
//返回值类型为bool，可以定义为成员函数或友元函数
    friend bool operator == ( Shape &robj1, Shape &robj2);
    friend bool operator > ( Shape &robj1, Shape &robj2);
    friend bool operator < ( Shape &robj1, Shape &robj2);
};
//函数实现
bool operator == (Shape &robj1, Shape &robj2)
{
    //比较两个double是否相等，不能直接用==
    //两个小数的差在可接受的精度范围内就可以被认为是相等的
   return ( abs( robj1.Area() - robj2.Area() ) < 1.0e-8 );
}

bool operator > ( Shape &robj1, Shape &robj2)
{
    if ( robj1.Area() > robj2.Area() )
    {
        return true;
    }
    else
        return false;
}

bool operator < ( Shape &robj1, Shape &robj2)
{
    if ( robj1.Area() < robj2.Area() )
    {
        return true;
    }
    else
        return false;
}

//形状类Shape派生矩形类Rectangle
class Rectangle : public Shape
{
    //添加double型的保护数据成员：rectWidth和rectHeight，分别表示矩形的宽度和高度
protected:
    double rectWidth;
    double rectHeight;
public:
    //定义带参构造函数
    Rectangle( double iniWidth = 0.0, double iniHeight = 0.0 ) : rectWidth(iniWidth), rectHeight(iniHeight) {}
    //重定义公有成员函数Show，打印矩形的宽度和高度
    //输出格式为“W: 宽度; H: 高度; Area: 面积”
    void Show();
    //重定义公有成员函数Area，计算矩形面积。
    double Area();
};

//Rectangle类实现部分
void Rectangle :: Show()
{
    cout << "W: " << rectWidth << "; " << "H:" << rectHeight << "; " <<"Area: " << Area() <<endl;
}
double Rectangle :: Area()
{
    return rectWidth * rectHeight ;
}

//从形状类Shape派生椭圆类Ellipse
class Ellipse : public Shape
{
    //添加double型的保护数据成员：rectWidth和rectHeight
    //分别表示椭圆外接矩形的宽度和高度
protected:
    double rectWidth;
    double rectHeight;
public:
    //定义带参构造函数；
    Ellipse( double iniWidth = 0.0, double iniHeight = 0.0 ) : rectWidth(iniWidth), rectHeight(iniHeight) {}
    //重定义公有成员函数Show，打印椭圆外接矩形的宽度和高
    //输出格式为“W: 宽度; H: 高度; Area: 面积”
    void Show();
    //重定义公有成员函数Area，计算椭圆面积
    double Area();
};
//Ellipse类实现部分
void Ellipse :: Show()
{
    cout << "W: " << rectWidth << "; " << "H:" << rectHeight << "; " <<"Area: " << Area() <<endl;
}
double Ellipse :: Area()
{
    return 3.1415926 * (rectWidth * 0.5 )* ( rectHeight * 0.5 );
}

int main()
{
    //首先根据输入的整数创建相应大小的Shape对象指针数组
    int num;
    cin >> num;
    Shape* *pArray = new Shape* [num];

    //再根据输入的对象类型和信息动态创建相应类型的对象,并关联到对象指针数组
    string objType;
    double rectWidth, rectHeight;

    int i;
    for( i = 0; i < num ; i++ )
    {
        cin >> objType >> rectWidth >> rectHeight;

        assert( objType == "R" || "E");

        if ( objType == "R" )
        {
            pArray[ i ] = new Rectangle ( rectWidth, rectHeight );
        }
        else if ( objType == "E" )
        {
            pArray[ i ] = new Ellipse ( rectWidth, rectHeight );
        }
    }

    //接着通过调用Show成员函数输出所有对象的信息
    for( i = 0; i < num ; i++ )
    {
        pArray[ i ] -> Show();
    }

    //然后输出面积相等的形状对象的信息
    //要求使用重载的运算符“==”来判断对象的面积是否相等
    int j;
    for( i = 0  ; i < num ; i++ )
    {
        for ( j = i + 1 ; j < num ; j++ )
        {
            if (  pArray[ i ] -> Area() == pArray[ j ] -> Area() )
            {
                cout << "Area of Shape[" << i << "] is equal to Shape[" << j << "]" <<endl;
            }
        }
    }
    //最后将所有形状对象按面积从大到小排序
    //（要求使用重载的运算符“>”来判断对象的面积的大小关系），并输出排序后的对象信息
    //冒泡排序
    Shape* temp;
    for( i = 0  ; i < num - 1 ; i++ )
    {
        for ( j = 0 ; j < num - 1 - i ; j++ )
        {
            if ( pArray[ j ] -> Area() < pArray[ j + 1 ] -> Area() )
            {
                temp = pArray[ j ];

                pArray[ j ] = pArray[ j + 1 ];

                pArray[ j + 1 ] = temp;
            }
        }
    }

    //输出排序后的对象信息
    for( i = 0; i < num ; i++ )
    {
        pArray[ i ] -> Show();
    }

    //销毁
    for( i = 0; i < num ; i++ )
    {
        if( pArray[ i ] )
        {
            delete pArray[ i ]; //释放指向的对象的内存
        }
    }

    //释放指向对象的指针数组

    delete[] pArray;

    return 0;
}